package org.softmed.neodatis.util.provider;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.neodatis.odb.ODB;
import org.neodatis.odb.ODBFactory;
import org.neodatis.odb.ODBServer;
import org.softmed.neodatis.util.PrimaryKeyManager;
import org.softmed.neodatis.util.trigger.TriggerEnvironment;

public class ServerWrapper {

	Map<String, PrimaryKeyManager> pkeyManagers = new HashMap<String, PrimaryKeyManager>();
	Map<String, TriggerEnvironment> triggerEnvironments = new HashMap<String, TriggerEnvironment>();
	Map<String, String> files = new HashMap<String, String>();
	List<String> bases = new ArrayList<String>();

	ODBServer server;
	int port = 7600;
	boolean running = false;

	public ServerWrapper() {
	}

	public String getDatabaseFile(String dbName) {
		return files.get(dbName);
	}

	public PrimaryKeyManager getPrimaryKeyManager(String dbName) {
		return pkeyManagers.get(dbName);
	}

	public void stopServer() throws Throwable {
		if (running) {
			server.close();
			bases.clear();
			files.clear();
			triggerEnvironments.clear();
			pkeyManagers.clear();
			running = false;
		}
	}

	public ServerWrapper(String dbName, String dbFileName) throws Throwable {
		registerODB(dbName, dbFileName);
	}

	public void startupServer() throws Throwable {
		if (!running) {
			server = getODBServer(port);
			running = true;
		}
	}

	public ODBServer getServer() {
		return server;
	}

	public void setServer(ODBServer server) {
		this.server = server;
	}

	public Map<String, TriggerEnvironment> getTriggerEnvironments() {
		return triggerEnvironments;
	}

	public void registerTriggerEnvironments(String name, TriggerEnvironment tenv) {
		triggerEnvironments.put(name, tenv);
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public ODB getODB(String dbName) throws Throwable {
		ODB odb = server.openClient(dbName);
		TriggerEnvironment env = triggerEnvironments.get(dbName);
		if (env != null)
			return env.setup(odb);

		return odb;
	}

	public ODB getCleanODB(String dbName) throws Throwable {
		ODB odb = server.openClient(dbName);
		return odb;
	}

	public void registerODB(String dbName, String dbFileName) throws Throwable {
		startupServer();

		if (bases.contains(dbName) || files.values().contains(dbFileName))
			throw new RuntimeException("ODB Name " + dbName
					+ " and/or filename " + dbFileName + " already registered");

		server.addBase(dbName, dbFileName);
		files.put(dbName, dbFileName);
		bases.add(dbName);
		pkeyManagers.put(dbName, new PrimaryKeyManager());

	}

	public static ODBServer getODBServer(int port) {

		try {
			// Creates the server on port odbServer =
			ODBServer server = ODBFactory.openServer(port);
			// Tells the server to manage base dbName that points to the file
			// dbFileName

			return server;
		} catch (Throwable t) {
			t.printStackTrace();
			System.exit(-1);
		}
		return null;

	}

}
